/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tools.compass;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.GpsStatus;
import android.location.GpsStatus.Listener;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.GestureDetector.OnGestureListener;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.mapapi.BMapManager;
import com.tools.compass.util.CommonUtil;
import com.tools.compass.util.Constants;
import com.tools.compass.util.LogI;
import com.tools.compass.util.SharedPref;
import com.tools.compass.util.ToastI;
import com.umeng.analytics.MobclickAgent;
import com.umeng.fb.UMFeedbackService;
import com.umeng.update.UmengDownloadListener;
import com.umeng.update.UmengUpdateAgent;
import com.umeng.update.UmengUpdateListener;
import com.umeng.update.UpdateResponse;

public class CompassActivity extends Activity implements OnGestureListener,
		OnClickListener, OnTouchListener {

	private static final String TAG = "Compass";
	private static final int FLEEP_DISTANCE = 160;

	protected static final boolean DEBUG_SENSOR = false;
	protected static final boolean DEBUG_GPS = false;
	protected static final boolean DEBUG = false;

	private static final int DIALOG_AHOUT = 0x1001;
	private static final int DIALOG_QUIET = 0x1002;

	private static final int MSG_REFRESH_TEXT = 0x2001;
	private SharedPref sharedPref;
	private SensorManager mSensorManager;
	private static float[] mValues;
	private static CompassView compass;
	private static TextView compassDegree;
	private static boolean mHasDegree = false;
	private static TextView compassMatrix;
	private static boolean mHasMatrix = false;
	private boolean mIsFirst = true;
	private boolean mChangedCompass = false;
	private boolean mChangedCompassLayoutBg = false;
	private int mCompassDrawble;
	private int mCompassLayoutBg;
	private android.view.GestureDetector gestureDetector;
	private MyHandler mHandler;
	private GpsContentObserver gpsObserver;
	RelativeLayout compassLayout;
	private ImageView compassGuide;

	private com.baidu.mapapi.LocationListener mBmapLocationListener;

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.main);
		mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		compassMatrix = (TextView) findViewById(R.id.compass_matrix);
		compassMatrix.setOnClickListener(this);
		findViewById(R.id.main_place).setOnClickListener(this);

		// getLocation();
		compassLayout = (RelativeLayout) findViewById(R.id.compass_layout);

		sharedPref = SharedPref.getInstanse(this.getApplicationContext());
		compass = (CompassView) findViewById(com.tools.compass.R.id.compass);
		compassGuide = (ImageView) findViewById(com.tools.compass.R.id.compass_guide);
		compassGuide.setOnTouchListener(this);
		if (sharedPref.getCompassGuideShow(true)) {
			compassGuide.setVisibility(View.VISIBLE);
		} else {
			compassGuide.setVisibility(View.GONE);
		}
		compassDegree = (TextView) findViewById(R.id.compass_degree);
		gpsObserver = new GpsContentObserver(new Handler());

		// getContentResolver().registerContentObserver(
		// Uri.parse(Settings.ACTION_LOCATION_SOURCE_SETTINGS), true,
		// gpsObserver);

		mHandler = new MyHandler(this);
		gestureDetector = new android.view.GestureDetector(this);
		mCompassLayoutBg = sharedPref.getCompassLayoutBg(0);
		mCompassLayoutBg = mCompassLayoutBg > Constants.compass_layout_bg.length - 1 ? 0
				: mCompassLayoutBg;
		compassLayout
				.setBackgroundResource(Constants.compass_layout_bg[mCompassLayoutBg]);
		mCompassDrawble = sharedPref.getCompassDrawble(0);
		mCompassDrawble = mCompassDrawble > Constants.compasses.length - 1 ? 0
				: mCompassDrawble;
		compass.setImageResource(Constants.compasses[mCompassDrawble]);
		int coverId = Constants.compassCoveres[mCompassDrawble];
		if (coverId != -1) {
			compass.setBackgroundResource(coverId);
		} else {
			compass.setBackgroundDrawable(null);
		}
		initBMap();
		// registerLocationListener();

		MobclickAgent.setSessionContinueMillis(30);
		MobclickAgent.onError(this);
		// 如果想程序启动时自动检查是否需要更新， 把下面两行代码加在Activity 的onCreate()函数里。
		// UmengUpdateAgent.setUpdateOnlyWifi(false);
		// // 如果您同时使用了手动更新和自动检查更新，为了避免更新回调被多次调用，请加上下面这句代码
		// UmengUpdateAgent.setOnDownloadListener(null);
		// UmengUpdateAgent.update(this);
		mHandler.sendEmptyMessageDelayed(MSG_REFRESH_TEXT, 5000);

	}

	private void getLocation() {
		LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		List<String> enableProviders = locationManager.getProviders(true);
		if (enableProviders != null && !enableProviders.isEmpty()) {
			for (String provider : enableProviders) {

				Location location = locationManager
						.getLastKnownLocation(provider);
				if (location == null) {
					compassMatrix.setText(R.string.location_no);
					mHasMatrix = false;
					locationManager.requestLocationUpdates(provider, 10 * 1000,
							5, new MyLoctionListenr());

					locationManager
							.addGpsStatusListener(new GpsStatusListener());
				} else {

					String matrix = location.getLatitude() + ","
							+ location.getLongitude();
					compassMatrix.setText(matrix);
					mHasMatrix = true;
				}
			}
		} else {
			compassMatrix.setText(R.string.location_no);
			mHasMatrix = false;
		}
	}

	@Override
	protected void onResume() {
		if (DEBUG)
			Log.d(TAG, "onResume");
		if (mSensorManager != null) {
			mSensorManager.registerListener(mListener,
					SensorManager.SENSOR_ORIENTATION,
					SensorManager.SENSOR_DELAY_NORMAL);
		}
		startMap();
		super.onResume();
		MobclickAgent.onResume(this);

	}

	@Override
	protected void onPause() {
		if (mSensorManager != null) {
			mSensorManager.unregisterListener(mListener);
		}
		saveCustomCompass();
		getContentResolver().unregisterContentObserver(gpsObserver);
		stopMap();
		super.onPause();
		MobclickAgent.onPause(this);
	}

	/**
	 * 保存用户自定义指南针样式和背景
	 */
	private void saveCustomCompass() {
		if (mChangedCompass) {
			sharedPref.putCompassDrawble(mCompassDrawble);
		}
		if (mChangedCompassLayoutBg) {
			sharedPref.putCompassLayoutBg(mCompassLayoutBg);
		}
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (sharedPref.getCompassGuideShow(true)) {
				compassGuide.setVisibility(View.GONE);
				return false;
			} else {
				showDialog(DIALOG_QUIET);
				return false;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.activity_main, menu);

		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_comment:
			// 如果没有安装市场则隐藏评分
			Intent intent = new Intent(Intent.ACTION_VIEW,
					Uri.parse("market://details?id=" + this.getPackageName()));
			List<ResolveInfo> resloves = this.getPackageManager()
					.queryIntentActivities(intent, 0);
			if (resloves != null && resloves.size() > 0) {
				startActivity(Intent.createChooser(intent, getString(R.string.app_name)));
			} else {
				// TODO 跳转到浏览器
			}
			break;
		case R.id.menu_feedback:
			// http://dev.umeng.com/doc/document_fb_android.html###
			UMFeedbackService.setGoBackButtonVisible();
			UMFeedbackService.openUmengFeedbackSDK(this);
			break;
		case R.id.menu_update:
			if (CommonUtil.IsNetworkAvailable(getApplicationContext())) {
				// 如果想程序启动时自动检查是否需要更新， 把下面两行代码加在Activity 的onCreate()函数里。
				com.umeng.common.Log.LOG = false;
				UmengUpdateAgent.setUpdateOnlyWifi(false); // 目前我们默认在Wi-Fi接入情况下才进行自动提醒。如需要在其他网络环境下进行更新自动提醒，则请添加该行代码
				UmengUpdateAgent.setUpdateAutoPopup(false);
				UmengUpdateAgent.setUpdateListener(mUpdateListener);

				UmengUpdateAgent
						.setOnDownloadListener(new UmengDownloadListener() {

							@Override
							public void OnDownloadEnd(int result) {
								// Toast.makeText(CompassActivity.this,
								// "download result : " + result,
								// Toast.LENGTH_SHORT)
								// .show();
							}

						});

				UmengUpdateAgent.update(CompassActivity.this);
			} else {
				Toast.makeText(getApplicationContext(), R.string.net_bad,
						Toast.LENGTH_LONG).show();
			}

			break;
		case R.id.menu_about:
			showDialog(DIALOG_AHOUT);
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		switch (id) {
		case DIALOG_AHOUT:
			String version = Constants.defaultVer;
			try {
				version = getPackageManager().getPackageInfo(getPackageName(),
						0).versionName;
			} catch (Exception e) {
				e.printStackTrace();
			}
			builder.setTitle(R.string.app_name)
					.setIcon(R.drawable.ic_launcher)
					.setMessage(
							getResources().getString(R.string.about_msg,
									version))
					.setPositiveButton(R.string.positive,
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							});

			return builder.create();

		case DIALOG_QUIET:
			builder.setTitle(R.string.notice)
					.setIcon(R.drawable.ic_launcher)
					.setMessage(getResources().getString(R.string.quite_tip))
					.setPositiveButton(R.string.positive,
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									CompassActivity.this.finish();
								}
							})
					.setNegativeButton(R.string.cancel,
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							});

			return builder.create();

		}
		return super.onCreateDialog(id);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		if (gestureDetector.onTouchEvent(event)) {
			event.setAction(MotionEvent.ACTION_CANCEL);
		}
		// compass.dispatchTouchEvent(event);
		return super.dispatchTouchEvent(event);
	}

	@Override
	public boolean onDown(MotionEvent e) {
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {

	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {

	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		if (DEBUG) {

			Log.i(TAG, "compass.getLeft():" + compass.getLeft());
			Log.i(TAG, "compass.getRight():" + compass.getRight());
			Log.i(TAG, "compass.getTop():" + compass.getTop());
			Log.i(TAG, "compass.getBottom():" + compass.getBottom());
			Log.i(TAG, "e1.getX()" + e1.getX());
			Log.i(TAG, "e1.getY()" + e1.getY());
			Log.i(TAG, "e2.getX()" + e2.getX());
			Log.i(TAG, "e2.getY()" + e2.getY());
		}

		int compassLen = Constants.compasses.length;
		int compassLayoutBgLen = Constants.compass_layout_bg.length;
		if (e1.getX() - e2.getX() >= FLEEP_DISTANCE) {// 从右向左滑动
			mCompassDrawble -= 1;
			mCompassLayoutBg -= 1;
			if (mCompassDrawble < 0) {
				mCompassDrawble = Constants.compasses.length - 1;
			}
			if (mCompassLayoutBg < 0) {
				mCompassLayoutBg = compassLayoutBgLen - 1;
			}
			mChangedCompass = true;
			mChangedCompassLayoutBg = true;
		} else if (e2.getX() - e1.getX() >= FLEEP_DISTANCE) {// 从左往右滑动
			mCompassDrawble += 1;
			mCompassLayoutBg += 1;

			if (mCompassDrawble > compassLen - 1) {
				mCompassDrawble = 0;
			}
			if (mCompassLayoutBg > compassLayoutBgLen - 1) {
				mCompassLayoutBg = 0;
			}
			mChangedCompass = true;
			mChangedCompassLayoutBg = true;

		}
		// 滑动焦点落在指南针上，则更换指南针样式
		if (compass.getLeft() < e1.getX() && compass.getRight() > e1.getX()
				&& compass.getTop() + 50 < e1.getY()
				&& compass.getBottom() - 50 > e1.getY()
				&& compass.getLeft() < e2.getX()
				&& compass.getRight() > e2.getX()
				&& compass.getTop() + 50 < e2.getY()
				&& compass.getBottom() - 50 > e2.getY()) {
			compass.setImageDrawable(getResources().getDrawable(
					Constants.compasses[mCompassDrawble]));
			int coverId = Constants.compassCoveres[mCompassDrawble];
			if (coverId != -1) {
				compass.setBackgroundResource(coverId);

			} else {
				compass.setBackgroundDrawable(null);
			}
			compass.invalidate();
		} else {
			compassLayout
					.setBackgroundResource(Constants.compass_layout_bg[mCompassLayoutBg]);
		}
		return false;
	}

	private void initBMap() {
		CompassApp app = (CompassApp) this.getApplication();
		if (app.mBMapMan == null) {
			app.mBMapMan = new BMapManager(getApplication());
			app.mBMapMan.init(app.mStrKey, new CompassApp.MyGeneralListener());
		}
		app.mBMapMan.start();

		// 注册定位事件
		mBmapLocationListener = new com.baidu.mapapi.LocationListener() {

			@Override
			public void onLocationChanged(Location location) {
				if (location != null) {
					BigDecimal decimal = new BigDecimal(location.getLatitude());
					String latitude = decimal.setScale(2,
							BigDecimal.ROUND_CEILING).toString();
					decimal = new BigDecimal(location.getLongitude());
					String longitude = decimal.setScale(2,
							BigDecimal.ROUND_CEILING).toString();
					compassMatrix.setText(getString(R.string.compass_matrix,
							latitude, longitude));
					mHasMatrix = true;
				}
			}
		};
	}

	private void startMap() {
		CompassApp app = (CompassApp) this.getApplication();
		// 注册Listener
		app.mBMapMan.getLocationManager().requestLocationUpdates(
				mBmapLocationListener);
		app.mBMapMan.start();
	}

	private void stopMap() {
		CompassApp app = (CompassApp) this.getApplication();
		// 移除listener
		app.mBMapMan.getLocationManager().removeUpdates(mBmapLocationListener);
		app.mBMapMan.stop();
	}

	private void registerLocationListener() {
		LocationManager locationMgr = (LocationManager) this
				.getSystemService(Context.LOCATION_SERVICE);
		Location location = locationMgr
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		if (location == null) {
			compassMatrix.setText("location is null");
			mHasMatrix = false;
		} else {

			compassMatrix.setText("Last/Latitude:" + location.getLatitude()
					+ "/Longitude:" + location.getLongitude());
			mHasMatrix = true;
		}
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setBearingRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_LOW);
		String provider = locationMgr.getBestProvider(criteria, true);
		if (DEBUG_GPS)
			LogI.i("BestProvider:" + provider);
		if (!TextUtils.isEmpty(provider)) {
			locationMgr.requestLocationUpdates(provider, 1000, 5,
					mLocationListener);
		}
		locationMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,
				5, mLocationListener);
		locationMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
				1000, 5, mLocationListener);
		locationMgr.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
				1000, 5, mLocationListener);
	}

	LocationListener mLocationListener = new LocationListener() {

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onProviderDisabled(String provider) {
			compassMatrix.setText("ProviderDisabled");
			mHasMatrix = false;

		}

		@Override
		public void onLocationChanged(Location location) {
			if (location == null) {
				compassMatrix.setText("null");
				mHasMatrix = false;

			} else {

				compassMatrix.setText("Latitude:" + location.getLatitude()
						+ "/Longitude:" + location.getLongitude());
				mHasMatrix = true;

			}

		}
	};

	static class MyHandler extends Handler {
		WeakReference<Activity> mActivity;

		MyHandler(Activity activity) {
			mActivity = new WeakReference<Activity>(activity);

		};

		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case 0:
				float degrees = -mValues[0];
				if (degrees > 0) {
					for (float i = 0; i <= degrees; i++) {
						compass.updateDirection(i);
					}
				} else {
					for (float i = 0; i <= degrees; i--) {
						compass.updateDirection(i);

					}
				}

				break;
			case 1:

				break;
			case MSG_REFRESH_TEXT:
				if (!mHasMatrix) {
					compassMatrix.setText(R.string.compass_matrix_no);
				}

				if (!mHasDegree) {
					compassDegree.setText(R.string.err);
				}
			}

		};
	};

	@SuppressWarnings("deprecation")
	private final SensorListener mListener = new SensorListener() {

		public void onSensorChanged(int sensor, float[] values) {
			if (DEBUG_SENSOR)
				Log.d(TAG, "sensorChanged (" + values[0] + ", " + values[1]
						+ ", " + values[2] + ")");// values[1]：纵向旋转角，0＝面朝上平置、-90＝垂直向上、-180/180＝面朝下平置、90＝垂直向
			// values[2]：橫向旋转角，0＝朝前、90＝往右倒、-90＝往左
			mValues = values;
			if (compass != null) {
				// if (mIsFirst) {
				// mHandler.sendEmptyMessage(0);
				// mIsFirst = false;
				// } else {
				if (mValues != null && mValues.length > 0
						&& !Float.isNaN(mValues[0])) {
					compass.updateDirection(-mValues[0]);
					if (DEBUG) {
						LogI.i("mValues[0]:" + mValues[0]);
					}
					BigDecimal bd = new BigDecimal(mValues[0]);
					int degree = bd.setScale(0, BigDecimal.ROUND_HALF_UP)
							.intValue();
					compassDegree.setText(CommonUtil.getDegreeText(
							CompassActivity.this, degree));
					mHasDegree = true;
				}
				// }

			}
		}

		public void onAccuracyChanged(int sensor, int accuracy) {
			if (DEBUG_SENSOR)
				Log.d(TAG, "onAccuracyChanged,sensor: " + sensor
						+ ",accuracy: " + accuracy);
		}
	};

	class MyLoctionListenr implements LocationListener {

		@Override
		public void onLocationChanged(Location location) {
			if (DEBUG) {
				ToastI.showShort(CompassActivity.this, "onLocationChanged");
			}
			location.getLongitude();
			location.getLatitude();
			compassMatrix.setText(location.getLongitude() + "/"
					+ location.getLatitude());
			mHasMatrix = true;

		}

		@Override
		public void onProviderDisabled(String provider) {

		}

		@Override
		public void onProviderEnabled(String provider) {

		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {

		}

	}

	class GpsStatusListener implements Listener {

		@Override
		public void onGpsStatusChanged(int event) {
			switch (event) {
			case GpsStatus.GPS_EVENT_FIRST_FIX:

				break;
			case GpsStatus.GPS_EVENT_SATELLITE_STATUS:

				break;
			case GpsStatus.GPS_EVENT_STARTED:

				break;
			case GpsStatus.GPS_EVENT_STOPPED:

				break;
			}
		}
	}

	class GpsContentObserver extends ContentObserver {
		public GpsContentObserver(Handler handler) {
			super(handler);
		}

		@Override
		public void onChange(boolean selfChange) {
		}
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.main_place:
			startActivity(new Intent(this, LocationOverlay.class));
			break;
		case R.id.compass_matrix:
			if (!mHasMatrix
					&& !CommonUtil.IsNetworkAvailable(getApplicationContext())) {
				CommonUtil.setSettings(getApplicationContext());
			}
			break;
		default:
			break;
		}
	}

	UmengUpdateListener mUpdateListener = new UmengUpdateListener() {
		@Override
		public void onUpdateReturned(int updateStatus, UpdateResponse updateInfo) {
			switch (updateStatus) {
			case 0: // has update
				UmengUpdateAgent.showUpdateDialog(CompassActivity.this,
						updateInfo);
				break;
			case 1: // has no update
				ToastI.showShort(CompassActivity.this, R.string.update_no);
				break;
			case 2: // none wifi
				ToastI.showShort(CompassActivity.this,
						R.string.update_wifi_only);
				break;
			case 3: // time out
				ToastI.showShort(CompassActivity.this, R.string.update_timeout);

				break;
			}

		}
	};

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch (v.getId()) {
		case R.id.compass_guide:
			compassGuide.setVisibility(View.GONE);
			SharedPref.getInstanse(this.getApplicationContext())
					.putCompassGuide(false);
			break;

		default:
			break;
		}
		return false;
	}

}
